#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <functional>
#include <iostream>
#include <chrono>
#include <vector>
#include <list>

/// \brief Session处理
class Session : public boost::enable_shared_from_this<Session>
{
public:
	/// \brief shared pointer
	typedef boost::shared_ptr<Session> Pointer;
	static Pointer create(boost::asio::io_service& io_service)
	{
		return Pointer(new Session(io_service));
	}

	Session(boost::asio::io_service &ios)
		: m_socket(ios)
	{}

	~Session()
	{
		m_socket.cancel();
		m_socket.close();
		std::cout << "close session: " << m_remote_addr << ":" << m_remote_port << std::endl;
	}

	/// \brief 启动session
	void start()
	{
		// 启动异步读取
		m_socket.async_read_some(boost::asio::buffer(m_buff, 1024),
					boost::bind(&Session::asyncRecv, this,
					::_1, ::_2));

		m_remote_addr = m_socket.remote_endpoint().address();
		m_remote_port = m_socket.remote_endpoint().port();
		std::cout << "start session: " << m_remote_addr << ":" << m_remote_port << std::endl;
	}

	/// \brief 获取socket
	boost::asio::ip::tcp::socket& socket() { return m_socket; }

	/// \brief async write
	void asyncWrite(const char* send_data, int32_t len)
	{
		boost::asio::async_write(m_socket, boost::asio::buffer(send_data, len),
        boost::bind(&Session::handleWrite, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred));
	}

	/// \brief is_error
	bool isError() { return m_on_error; }
	
private:
	/// \brief 异步接收
	void asyncRecv(const boost::system::error_code& error,  uint32_t read_size)
	{
		if (error){
			//std::cout << "async error :" << error << std::endl;
			m_on_error = true;
		}
		else
		{
			std::cout << "asyncRecv\n";

			// 处理完成开始新的接收
			m_socket.async_read_some(boost::asio::buffer(m_buff, 1024),
						boost::bind(&Session::asyncRecv, this,
						::_1, ::_2));
		}
	}

	void handleWrite(const boost::system::error_code& ec,size_t send_size)
	{
		if (ec){
			m_on_error = true;
		}
	}

	/// \brief async send
	void asyncSend(){}

private:
	bool m_on_error = false;
	char m_buff[2048];
	boost::asio::ip::tcp::socket m_socket;
	boost::asio::ip::address m_remote_addr;
	int32_t m_remote_port;
};
typedef boost::shared_ptr<Session> SessionPtr;		// socket智能指针

// 异步服务器类
class Server
{
public:
	/// \brief server构造
	Server(boost::asio::io_service &_ios) :
		ios_(_ios),
		acceptor_(_ios, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 6688)),
		m_timer(_ios)
	{
		startAccept(); // 默认执行, 开启异步侦听
		m_timer.expires_from_now(std::chrono::milliseconds(100));
		m_timer.async_wait(boost::bind(&Server::asyncTimer, this, ::_1));
	}

	// 启动网络侦听的操作入口
	void startAccept(void)
	{
		auto new_session = Session::create(ios_);

		// 异步侦听，若有服务连接，则自动调用Server::handler_accept函数，并将error, socket传入作为参数
		acceptor_.async_accept(new_session->socket(), boost::bind(&Server::acceptHandler,
						this, new_session, boost::asio::placeholders::error));
	}

	// 请求者响应后触发的处理器
	void acceptHandler(Session::Pointer new_session, const boost::system::error_code &_ec)
	{
		// 错误码检测
		if (_ec) {
			return;
		}
		m_sessions.emplace_back(new_session);
		new_session->start();

		startAccept();	// 启动新的异步监听
	}

	// 完成异步写操作后的处理器
	void writeHandle(const boost::system::error_code &_ec)
	{
		std::cout << "server: send message complete." << std::endl;
	}

	/// \brief 异步定时器
	void asyncTimer(const boost::system::error_code &ec)
	{
		for (auto it = m_sessions.begin(); it != m_sessions.end(); it++){
			if ((*it)->isError()) {
				it = m_sessions.erase(it);
			}
		}
		for (const auto &it : m_sessions){
			it->asyncWrite("1234", 4);
		}
		m_timer.expires_from_now(std::chrono::milliseconds(100));
		m_timer.async_wait(boost::bind(&Server::asyncTimer, this, ::_1));
	}

private:
	boost::asio::steady_timer m_timer;
	boost::asio::io_service &ios_;								// 服务实例
	boost::asio::ip::tcp::acceptor acceptor_;					// 接收器实例
	std::list<Session::Pointer> m_sessions;			// sessions
};


/// \brief main
int main(void)
{
    try {
        std::cout << "server start." << std::endl;
        boost::asio::io_service ios;	// 建造服务对象
        Server server(ios);				// 构建Server实例
        ios.run();						// 启动异步调用事件处理循环
    } catch (std::exception &_e) {
        std::cout << _e.what() << std::endl;
    }
    std::cout << "server end." << std::endl;
    return 0;
}